
package com.seekting.gongzhu.clientsdk;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import com.seekting.gongzhu.sdk.Info;
import com.seekting.gongzhu.sdk.KLog;

public class ExecetorServiceFinder implements ServiceFinder {

    private static final int TIME_OUT = 10;

    public ExecetorServiceFinder() {
    }

    @Override
    public void find(final FindListener findListener) {

        App.THREAD_POOL_EXECUTOR.execute(new Runnable() {

            @Override
            public void run() {
                IpPort ipPort = find();
                if (findListener != null) {
                    if (ipPort == null) {
                        findListener.onNotFind();
                    } else {

                        findListener.onFind(ipPort.getIp());
                    }
                }
            }
        });
    }

    public IpPort find() {
        List<FindIpTask> list = new ArrayList<FindIpTask>();
        for (int i = 0; i < 10; i++) {
            int port = Info.UDP_LOCAL_PORT + i;
            list.add(new FindIpTask(port));
        }
        try {
            IpPort ipPort = App.THREAD_POOL_EXECUTOR.invokeAny(list, TIME_OUT, TimeUnit.SECONDS);

            return ipPort;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        } finally {
            for (FindIpTask task : list) {
                task.close();
            }

        }
        return null;

    }

    private static class FindIpTask implements Callable<IpPort> {

        private int port;
        DatagramSocket datagramSocket;

        public void close() {
            if (datagramSocket != null) {
                datagramSocket.close();
            }
        }

        public FindIpTask(int port) {
            this.port = port;
            try {
                datagramSocket = new DatagramSocket(port);
            } catch (SocketException e) {
                e.printStackTrace();
            }
        }

        @Override
        public IpPort call() {

            try {

                if (datagramSocket == null) {
                    return null;
                }
                InetSocketAddress destAddress = new InetSocketAddress("255.255.255.255",
                        Info.UDP_PORT); // 目标广播地址+目标端口
                byte[] bytes = Info.UDP_GET_IP_REQUEST.getBytes();
                DatagramPacket data = new DatagramPacket(bytes, Info.UDP_GET_IP_REQUEST_LENGTH,
                        destAddress);

                datagramSocket.send(data);
                byte[] recByte = new byte[50];
                DatagramPacket receivePack = new DatagramPacket(recByte, recByte.length);
                System.out.println("等待获取ip回应");
                datagramSocket.receive(receivePack);
                SocketAddress inetAddress = receivePack.getSocketAddress();
                if (inetAddress != null) {
                    String str = inetAddress.toString();
                    String ip = str.substring(str.indexOf("/") + 1, str.indexOf(":"));
                    KLog.d("get ip from udp" + ip + ":" + this.port);
                    IpPort ipPort = new IpPort(ip, this.port);
                    return ipPort;
                }

            } catch (Exception e) {
                KLog.e("udp没有找到主机" + e.getMessage());
            }
            return null;
        }
    }
}
